import tkinter as tk
from tkinter import ttk, filedialog, messagebox, simpledialog
import threading
import time
import os
from datetime import datetime
import cv2
import numpy as np
import pyautogui
import sys
from typing import Dict, Tuple, Optional, List
import pyaudio
import wave
import json
import keyboard
from PIL import Image, ImageTk

class ScrollableFrame(tk.Frame):
    """可滚动的Frame容器"""
    def __init__(self, container, *args, **kwargs):
        super().__init__(container, *args, **kwargs)
        
        # 创建画布和滚动条
        self.canvas = tk.Canvas(self, borderwidth=0)
        self.scrollbar = ttk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
        self.scrollable_frame = tk.Frame(self.canvas)
        
        # 绑定滚动事件
        self.scrollable_frame.bind(
            "<Configure>",
            lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all"))
        )
        
        # 创建窗口并添加滚动条
        self.canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
        self.canvas.configure(yscrollcommand=self.scrollbar.set)
        
        # 绑定鼠标滚轮事件
        self.canvas.bind("<Enter>", self._bind_mousewheel)
        self.canvas.bind("<Leave>", self._unbind_mousewheel)
        
        # 布局
        self.canvas.pack(side="left", fill="both", expand=True)
        self.scrollbar.pack(side="right", fill="y")
        
    def _bind_mousewheel(self, event):
        self.canvas.bind_all("<MouseWheel>", self._on_mousewheel)
        
    def _unbind_mousewheel(self, event):
        self.canvas.unbind_all("<MouseWheel>")
        
    def _on_mousewheel(self, event):
        self.canvas.yview_scroll(int(-1*(event.delta/120)), "units")

class ScreenRecorder:
    def __init__(self, root):
        self.root = root
        self.root.title("WinScreenRecorder Pro")
        
        # 获取屏幕尺寸并设置窗口大小
        screen_width = root.winfo_screenwidth()
        screen_height = root.winfo_screenheight()
        
        # 根据屏幕尺寸调整窗口大小
        if screen_width >= 1920 and screen_height >= 1080:
            # 高分辨率屏幕
            window_width = min(1000, screen_width - 100)
            window_height = min(800, screen_height - 100)
            self.font_size_normal = 11
            self.font_size_large = 28
            self.font_size_small = 10
        else:
            # 普通分辨率屏幕
            window_width = 900
            window_height = 700
            self.font_size_normal = 10
            self.font_size_large = 24
            self.font_size_small = 9
            
        # 设置窗口位置居中
        x = (screen_width - window_width) // 2
        y = (screen_height - window_height) // 2
        
        self.root.geometry(f"{window_width}x{window_height}+{x}+{y}")
        self.root.minsize(800, 600)  # 设置最小窗口大小
        self.root.configure(bg='#f3f3f3')
        
        # 初始化变量
        self.recording = False
        self.paused = False
        self.start_time: Optional[float] = None
        self.elapsed_time = 0
        self.video_writer: Optional[cv2.VideoWriter] = None
        self.file_path = ""
        self.frame_count = 0
        self.actual_fps = 0
        self.audio_recording = False
        self.audio_thread = None
        self.audio_frames = []
        self.camera_recording = False
        self.camera = None
        self.camera_frame = None
        
        # 分辨率选项
        self.resolutions: Dict[str, Tuple[int, int]] = {
            "720p (1280×720)": (1280, 720),
            "1080p (1920×1080)": (1920, 1080),
            "2K (2560×1440)": (2560, 1440),
            "4K (3840×2160)": (3840, 2160),
            "全屏 (当前分辨率)": self.get_current_resolution()
        }
        
        # 固定帧率为20帧
        self.frame_rate = 20
        
        # 编码器选项
        self.codecs = {
            "MP4V (.mp4)": "mp4v",
            "XVID (.avi)": "XVID",
            "H264 (.mp4)": "H264"
        }
        
        # 音频设置
        self.audio = pyaudio.PyAudio()
        self.setup_audio_devices()
        
        # 快捷键设置
        self.hotkeys = {
            "start_recording": "F9",
            "stop_recording": "F10",
            "pause_resume": "F8"
        }
        self.load_hotkeys()
        
        self.setup_ui()
        
    def load_hotkeys(self):
        """加载保存的快捷键设置"""
        try:
            config_path = os.path.join(os.path.dirname(__file__), "recorder_config.json")
            if os.path.exists(config_path):
                with open(config_path, 'r') as f:
                    config = json.load(f)
                    if "hotkeys" in config:
                        self.hotkeys = config["hotkeys"]
        except Exception as e:
            print(f"加载快捷键设置失败: {e}")
            
    def save_hotkeys(self):
        """保存快捷键设置"""
        try:
            config_path = os.path.join(os.path.dirname(__file__), "recorder_config.json")
            config = {"hotkeys": self.hotkeys}
            with open(config_path, 'w') as f:
                json.dump(config, f, indent=4)
        except Exception as e:
            print(f"保存快捷键设置失败: {e}")
            
    def setup_audio_devices(self):
        """获取音频设备列表"""
        self.input_devices = []
        self.output_devices = []
        
        try:
            for i in range(self.audio.get_device_count()):
                device_info = self.audio.get_device_info_by_index(i)
                if device_info['maxInputChannels'] > 0:
                    self.input_devices.append((i, device_info['name']))
                if device_info['maxOutputChannels'] > 0:
                    self.output_devices.append((i, device_info['name']))
        except Exception as e:
            print(f"获取音频设备失败: {e}")
            self.input_devices = [(0, "默认麦克风")]
            self.output_devices = [(0, "默认扬声器")]
        
    def get_current_resolution(self) -> Tuple[int, int]:
        """获取当前屏幕分辨率"""
        try:
            screen_width = self.root.winfo_screenwidth()
            screen_height = self.root.winfo_screenheight()
            return (screen_width, screen_height)
        except:
            return (1920, 1080)
        
    def setup_ui(self):
        # 创建主滚动框架
        main_frame = ScrollableFrame(self.root)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 主标题栏
        header_frame = tk.Frame(main_frame.scrollable_frame, bg='#ffffff', relief='flat', bd=0)
        header_frame.pack(fill=tk.X, pady=(25, 15), padx=25)
        
        title_label = tk.Label(header_frame, text="WinScreenRecorder Pro", 
                              font=("Segoe UI", self.font_size_large, "bold"), 
                              bg='#ffffff', fg='#0067c0')
        title_label.pack()
        
        subtitle_label = tk.Label(header_frame, text="专业屏幕录制工具 - 支持音频和摄像头", 
                                 font=("Segoe UI", self.font_size_normal), 
                                 bg='#ffffff', fg='#666666')
        subtitle_label.pack(pady=(0, 15))
        
        # 设置面板
        settings_frame = tk.Frame(main_frame.scrollable_frame, bg='#ffffff', relief='groove', bd=1)
        settings_frame.pack(pady=15, padx=25, fill=tk.X)
        
        # 设置面板标题
        settings_title = tk.Label(settings_frame, text="录制设置", 
                                 font=('Segoe UI', self.font_size_normal, 'bold'),
                                 bg='#ffffff', fg='#000000')
        settings_title.pack(pady=(10, 15))
        
        # 使用网格布局让设置项更整齐
        settings_grid = tk.Frame(settings_frame, bg='#ffffff')
        settings_grid.pack(padx=20, pady=(0, 15), fill=tk.X)
        
        # 创建两列布局
        settings_grid.columnconfigure(1, weight=1)
        
        # 分辨率设置
        tk.Label(settings_grid, text="分辨率:", font=("Segoe UI", self.font_size_normal), 
                bg='#ffffff').grid(row=0, column=0, padx=12, pady=10, sticky=tk.W)
        self.resolution_var = tk.StringVar(value="全屏 (当前分辨率)")
        resolution_combo = ttk.Combobox(settings_grid, textvariable=self.resolution_var, 
                                      values=list(self.resolutions.keys()), state="readonly", 
                                      font=('Segoe UI', self.font_size_small), width=22)
        resolution_combo.grid(row=0, column=1, padx=12, pady=10, sticky=tk.W)
        
        # 帧率显示（固定为20帧）
        tk.Label(settings_grid, text="帧率 (FPS):", font=("Segoe UI", self.font_size_normal), 
                bg='#ffffff').grid(row=1, column=0, padx=12, pady=10, sticky=tk.W)
        fps_label = tk.Label(settings_grid, text="20 (固定)", font=("Segoe UI", self.font_size_small), 
                            bg='#ffffff', fg='#666666')
        fps_label.grid(row=1, column=1, padx=12, pady=10, sticky=tk.W)
        
        # 编码器设置
        tk.Label(settings_grid, text="编码格式:", font=("Segoe UI", self.font_size_normal), 
                bg='#ffffff').grid(row=2, column=0, padx=12, pady=10, sticky=tk.W)
        self.codec_var = tk.StringVar(value="MP4V (.mp4)")
        codec_combo = ttk.Combobox(settings_grid, textvariable=self.codec_var, 
                                  values=list(self.codecs.keys()), state="readonly", 
                                  font=('Segoe UI', self.font_size_small), width=15)
        codec_combo.grid(row=2, column=1, padx=12, pady=10, sticky=tk.W)
        
        # 音频录制设置
        tk.Label(settings_grid, text="音频输入:", font=("Segoe UI", self.font_size_normal), 
                bg='#ffffff').grid(row=3, column=0, padx=12, pady=10, sticky=tk.W)
        
        audio_frame = tk.Frame(settings_grid, bg='#ffffff')
        audio_frame.grid(row=3, column=1, padx=12, pady=10, sticky=tk.W)
        
        self.audio_var = tk.BooleanVar(value=False)
        audio_cb = tk.Checkbutton(audio_frame, text="启用麦克风录制", variable=self.audio_var,
                                 font=("Segoe UI", self.font_size_small), bg='#ffffff', command=self.toggle_audio_options)
        audio_cb.pack(side=tk.LEFT)
        
        # 音频设备选择
        self.audio_options_frame = tk.Frame(settings_grid, bg='#ffffff')
        self.audio_options_frame.grid(row=4, column=0, columnspan=2, padx=12, pady=5, sticky=tk.W)
        
        tk.Label(self.audio_options_frame, text="麦克风设备:", font=("Segoe UI", self.font_size_small), 
                bg='#ffffff').pack(side=tk.LEFT, padx=(20, 5))
        
        # 获取麦克风设备名称列表
        mic_names = [f"{idx}: {name}" for idx, name in self.input_devices]
        self.mic_var = tk.StringVar(value=mic_names[0] if mic_names else "")
        self.mic_combo = ttk.Combobox(self.audio_options_frame, textvariable=self.mic_var, 
                                     values=mic_names, state="readonly", 
                                     font=('Segoe UI', self.font_size_small), width=30)
        self.mic_combo.pack(side=tk.LEFT)
        
        # 初始隐藏音频选项
        self.audio_options_frame.grid_remove()
        
        # 摄像头录制设置
        tk.Label(settings_grid, text="摄像头:", font=("Segoe UI", self.font_size_normal), 
                bg='#ffffff').grid(row=5, column=0, padx=12, pady=10, sticky=tk.W)
        
        camera_frame = tk.Frame(settings_grid, bg='#ffffff')
        camera_frame.grid(row=5, column=1, padx=12, pady=10, sticky=tk.W)
        
        self.camera_var = tk.BooleanVar(value=False)
        camera_cb = tk.Checkbutton(camera_frame, text="启用摄像头画中画", variable=self.camera_var,
                                  font=("Segoe UI", self.font_size_small), bg='#ffffff', command=self.toggle_camera_options)
        camera_cb.pack(side=tk.LEFT)
        
        # 摄像头预览
        self.camera_preview_frame = tk.Frame(settings_grid, bg='#ffffff')
        self.camera_preview_frame.grid(row=6, column=0, columnspan=2, padx=12, pady=5, sticky=tk.W)
        
        self.camera_preview_label = tk.Label(self.camera_preview_frame, text="摄像头预览", 
                                            font=("Segoe UI", self.font_size_small), bg='#e0e0e0', 
                                            width=40, height=10)
        self.camera_preview_label.pack()
        
        # 初始隐藏摄像头预览
        self.camera_preview_frame.grid_remove()
        
        # 快捷键设置
        tk.Label(settings_grid, text="快捷键:", font=("Segoe UI", self.font_size_normal), 
                bg='#ffffff').grid(row=7, column=0, padx=12, pady=10, sticky=tk.W)
        
        hotkey_frame = tk.Frame(settings_grid, bg='#ffffff')
        hotkey_frame.grid(row=7, column=1, padx=12, pady=10, sticky=tk.EW)
        
        # 开始录制快捷键
        start_hotkey_frame = tk.Frame(hotkey_frame, bg='#ffffff')
        start_hotkey_frame.pack(fill=tk.X, pady=2)
        tk.Label(start_hotkey_frame, text="开始录制:", font=("Segoe UI", self.font_size_small), 
                bg='#ffffff').pack(side=tk.LEFT)
        self.start_hotkey_btn = tk.Button(start_hotkey_frame, text=self.hotkeys["start_recording"],
                                        command=lambda: self.change_hotkey("start_recording"),
                                        font=("Segoe UI", self.font_size_small), width=10)
        self.start_hotkey_btn.pack(side=tk.RIGHT, padx=5)
        
        # 停止录制快捷键
        stop_hotkey_frame = tk.Frame(hotkey_frame, bg='#ffffff')
        stop_hotkey_frame.pack(fill=tk.X, pady=2)
        tk.Label(stop_hotkey_frame, text="停止录制:", font=("Segoe UI", self.font_size_small), 
                bg='#ffffff').pack(side=tk.LEFT)
        self.stop_hotkey_btn = tk.Button(stop_hotkey_frame, text=self.hotkeys["stop_recording"],
                                       command=lambda: self.change_hotkey("stop_recording"),
                                       font=("Segoe UI", self.font_size_small), width=10)
        self.stop_hotkey_btn.pack(side=tk.RIGHT, padx=5)
        
        # 暂停/继续快捷键
        pause_hotkey_frame = tk.Frame(hotkey_frame, bg='#ffffff')
        pause_hotkey_frame.pack(fill=tk.X, pady=2)
        tk.Label(pause_hotkey_frame, text="暂停/继续:", font=("Segoe UI", self.font_size_small), 
                bg='#ffffff').pack(side=tk.LEFT)
        self.pause_hotkey_btn = tk.Button(pause_hotkey_frame, text=self.hotkeys["pause_resume"],
                                        command=lambda: self.change_hotkey("pause_resume"),
                                        font=("Segoe UI", self.font_size_small), width=10)
        self.pause_hotkey_btn.pack(side=tk.RIGHT, padx=5)
        
        # 文件保存位置
        tk.Label(settings_grid, text="保存位置:", font=("Segoe UI", self.font_size_normal), 
                bg='#ffffff').grid(row=8, column=0, padx=12, pady=10, sticky=tk.W)
        
        path_frame = tk.Frame(settings_grid, bg='#ffffff')
        path_frame.grid(row=8, column=1, padx=12, pady=10, sticky=tk.EW)
        path_frame.columnconfigure(0, weight=1)
        
        self.path_var = tk.StringVar(value=os.path.join(os.path.expanduser("~"), "Videos", "ScreenRecords"))
        os.makedirs(self.path_var.get(), exist_ok=True)
        
        path_entry = ttk.Entry(path_frame, textvariable=self.path_var, font=('Segoe UI', self.font_size_small))
        path_entry.grid(row=0, column=0, sticky=tk.EW, padx=(0, 8))
        
        browse_btn = tk.Button(path_frame, text="浏览", command=self.browse_path, 
                              font=('Segoe UI', self.font_size_small), bg='#0078d4', fg='white',
                              relief='flat', padx=15, pady=5)
        browse_btn.grid(row=0, column=1)
        
        # 计时器显示区域
        timer_frame = tk.Frame(main_frame.scrollable_frame, bg='#ffffff', relief='flat')
        timer_frame.pack(pady=15, padx=25, fill=tk.X)
        
        self.timer_label = tk.Label(timer_frame, text="00:00:00", 
                                   font=("Segoe UI", 42, "bold"), 
                                   bg='#ffffff', fg='#0078d4')
        self.timer_label.pack()
        
        # 帧数显示
        self.frame_count_label = tk.Label(timer_frame, text="帧数: 0", 
                                         font=("Segoe UI", self.font_size_small), 
                                         bg='#ffffff', fg='#666666')
        self.frame_count_label.pack()
        
        # 实际FPS显示
        self.fps_label = tk.Label(timer_frame, text="实际FPS: 0", 
                                 font=("Segoe UI", self.font_size_small), 
                                 bg='#ffffff', fg='#666666')
        self.fps_label.pack()
        
        # 控制按钮区域
        btn_frame = tk.Frame(main_frame.scrollable_frame, bg='#f3f3f3')
        btn_frame.pack(pady=20, padx=25)
        
        # 创建大按钮
        self.start_btn = tk.Button(btn_frame, text="🚀 开始录制", command=self.start_recording,
                                  font=('Segoe UI', 14, 'bold'), bg='#28a745', fg='white',
                                  relief='raised', padx=30, pady=15)
        self.start_btn.pack(side=tk.LEFT, padx=15)
        
        self.pause_btn = tk.Button(btn_frame, text="⏸️ 暂停", command=self.pause_recording,
                                  font=('Segoe UI', 14, 'bold'), bg='#ffc107', fg='black',
                                  relief='raised', padx=30, pady=15, state=tk.DISABLED)
        self.pause_btn.pack(side=tk.LEFT, padx=15)
        
        self.stop_btn = tk.Button(btn_frame, text="⏹️ 停止", command=self.stop_recording,
                                 font=('Segoe UI', 14, 'bold'), bg='#dc3545', fg='white',
                                 relief='raised', padx=30, pady=15, state=tk.DISABLED)
        self.stop_btn.pack(side=tk.LEFT, padx=15)
        
        # 提示信息
        info_frame = tk.Frame(main_frame.scrollable_frame, bg='#f3f3f3')
        info_frame.pack(pady=(15, 10), padx=25, fill=tk.X)
        
        self.info_label = tk.Label(info_frame, text=f"💡 提示：使用快捷键 {self.hotkeys['start_recording']} 开始录制，{self.hotkeys['stop_recording']} 停止录制，{self.hotkeys['pause_resume']} 暂停/继续", 
                              font=("Segoe UI", self.font_size_small), foreground='#666666', bg='#f3f3f3')
        self.info_label.pack()
        
        # 状态栏
        status_frame = tk.Frame(self.root, bg='#e8e8e8', relief='sunken', bd=1)
        status_frame.pack(side=tk.BOTTOM, fill=tk.X)
        
        self.status_var = tk.StringVar(value="🟢 准备就绪")
        status_bar = tk.Label(status_frame, textvariable=self.status_var, 
                             anchor=tk.W, padx=10, pady=8,
                             font=('Segoe UI', self.font_size_small), bg='#e8e8e8', fg='#000000')
        status_bar.pack(fill=tk.X)
        
        # 设置全局快捷键
        self.setup_hotkeys()
        
        # 启动摄像头预览更新
        self.update_camera_preview()
        
        # 绑定窗口大小变化事件
        self.root.bind("<Configure>", self.on_window_resize)
        
    def on_window_resize(self, event):
        """窗口大小变化时的回调函数"""
        if event.widget == self.root:
            # 更新状态栏信息
            if hasattr(self, 'status_var'):
                width = self.root.winfo_width()
                height = self.root.winfo_height()
                self.status_var.set(f"🟢 准备就绪 | 窗口大小: {width}x{height}")
        
    def change_hotkey(self, action):
        """修改快捷键"""
        # 获取当前快捷键
        current_hotkey = self.hotkeys[action]
        
        # 弹出对话框让用户输入新快捷键
        new_hotkey = simpledialog.askstring("修改快捷键", 
                                          f"请输入新的{action.replace('_', ' ')}快捷键:",
                                          initialvalue=current_hotkey)
        
        if new_hotkey:
            # 移除旧的快捷键
            try:
                if action == "start_recording":
                    keyboard.remove_hotkey(current_hotkey)
                elif action == "stop_recording":
                    keyboard.remove_hotkey(current_hotkey)
                elif action == "pause_resume":
                    keyboard.remove_hotkey(current_hotkey)
            except:
                pass
            
            # 更新快捷键
            self.hotkeys[action] = new_hotkey.upper()
            
            # 更新按钮文本
            if action == "start_recording":
                self.start_hotkey_btn.config(text=new_hotkey.upper())
            elif action == "stop_recording":
                self.stop_hotkey_btn.config(text=new_hotkey.upper())
            elif action == "pause_resume":
                self.pause_hotkey_btn.config(text=new_hotkey.upper())
            
            # 重新设置快捷键
            self.setup_hotkeys()
            
            # 保存设置
            self.save_hotkeys()
            
            # 更新提示信息
            self.update_info_label()
            
    def update_info_label(self):
        """更新提示信息"""
        self.info_label.config(
            text=f"💡 提示：使用快捷键 {self.hotkeys['start_recording']} 开始录制，{self.hotkeys['stop_recording']} 停止录制，{self.hotkeys['pause_resume']} 暂停/继续"
        )
        
    def toggle_audio_options(self):
        """显示或隐藏音频选项"""
        if self.audio_var.get():
            self.audio_options_frame.grid()
        else:
            self.audio_options_frame.grid_remove()
            
    def toggle_camera_options(self):
        """显示或隐藏摄像头预览"""
        if self.camera_var.get():
            self.camera_preview_frame.grid()
            # 初始化摄像头
            self.init_camera()
        else:
            self.camera_preview_frame.grid_remove()
            # 释放摄像头
            if self.camera:
                self.camera.release()
                self.camera = None
                
    def init_camera(self):
        """初始化摄像头"""
        try:
            if self.camera:
                self.camera.release()
                
            self.camera = cv2.VideoCapture(0)
            if not self.camera.isOpened():
                messagebox.showwarning("警告", "无法打开摄像头，请检查摄像头连接")
                self.camera_var.set(False)
                self.camera_preview_frame.grid_remove()
                return
                
            # 设置摄像头分辨率
            self.camera.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
            self.camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
            
        except Exception as e:
            messagebox.showerror("错误", f"初始化摄像头失败: {str(e)}")
            self.camera_var.set(False)
            self.camera_preview_frame.grid_remove()
            
    def update_camera_preview(self):
        """更新摄像头预览"""
        if self.camera_var.get() and self.camera and self.camera.isOpened():
            ret, frame = self.camera.read()
            if ret:
                # 调整帧大小
                frame = cv2.resize(frame, (320, 240))
                # 转换为RGB
                frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                
                # 使用PIL处理图像，提高兼容性
                img = Image.fromarray(frame)
                img = ImageTk.PhotoImage(img)
                
                self.camera_preview_label.config(image=img)
                self.camera_preview_label.image = img
                
        self.root.after(100, self.update_camera_preview)
        
    def setup_hotkeys(self):
        """设置全局快捷键"""
        try:
            # 移除所有已注册的快捷键
            keyboard.unhook_all()
            
            # 注册新的快捷键
            keyboard.add_hotkey(self.hotkeys["start_recording"].lower(), self.start_recording_hotkey)
            keyboard.add_hotkey(self.hotkeys["stop_recording"].lower(), self.stop_recording_hotkey)
            keyboard.add_hotkey(self.hotkeys["pause_resume"].lower(), self.pause_resume_hotkey)
            
        except Exception as e:
            print(f"设置快捷键失败: {e}")
        
    def start_recording_hotkey(self):
        """快捷键开始录制"""
        if not self.recording:
            self.start_recording()
            
    def stop_recording_hotkey(self):
        """快捷键停止录制"""
        if self.recording:
            self.stop_recording()
            
    def pause_resume_hotkey(self):
        """快捷键暂停/继续录制"""
        if self.recording:
            self.pause_recording()
            
    def browse_path(self):
        directory = filedialog.askdirectory(initialdir=self.path_var.get())
        if directory:
            self.path_var.set(directory)
            os.makedirs(directory, exist_ok=True)
            
    def update_timer(self):
        if self.recording and not self.paused:
            elapsed = time.time() - self.start_time + self.elapsed_time
            hours = int(elapsed // 3600)
            minutes = int((elapsed % 3600) // 60)
            seconds = int(elapsed % 60)
            self.timer_label.config(text=f"{hours:02d}:{minutes:02d}:{seconds:02d}")
            
            # 更新帧数显示
            self.frame_count_label.config(text=f"帧数: {self.frame_count}")
            
            # 更新实际FPS显示
            if elapsed > 0:
                self.actual_fps = self.frame_count / elapsed
                self.fps_label.config(text=f"实际FPS: {self.actual_fps:.1f}")
            
        self.root.after(1000, self.update_timer)
        
    def record_audio(self):
        """录制音频线程"""
        try:
            # 获取选中的麦克风设备索引
            mic_index = int(self.mic_var.get().split(":")[0])
            
            # 音频参数
            CHUNK = 1024
            FORMAT = pyaudio.paInt16
            CHANNELS = 2
            RATE = 44100
            
            # 打开音频流
            stream = self.audio.open(
                format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                input_device_index=mic_index,
                frames_per_buffer=CHUNK
            )
            
            self.audio_frames = []
            
            while self.audio_recording:
                if not self.paused:
                    data = stream.read(CHUNK)
                    self.audio_frames.append(data)
                else:
                    time.sleep(0.1)
                    
            # 停止并关闭流
            stream.stop_stream()
            stream.close()
            
        except Exception as e:
            print(f"音频录制错误: {e}")
            
    def start_recording(self):
        try:
            # 获取设置
            resolution = self.resolutions[self.resolution_var.get()]
            # 使用固定帧率20
            fps = self.frame_rate
            codec = self.codecs[self.codec_var.get()]
            save_path = self.path_var.get()
            
            # 检查保存路径
            if not os.path.exists(save_path):
                messagebox.showerror("错误", "保存路径不存在！")
                return
                
            # 生成文件名
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            file_ext = ".mp4" if "mp4" in self.codec_var.get().lower() else ".avi"
            self.file_path = os.path.join(save_path, f"screen_record_{timestamp}{file_ext}")
            
            # 初始化视频写入器
            fourcc = cv2.VideoWriter_fourcc(*codec)
            self.video_writer = cv2.VideoWriter(self.file_path, fourcc, fps, resolution)
            
            if not self.video_writer.isOpened():
                messagebox.showerror("错误", "无法创建视频文件，请检查保存路径和权限")
                return
                
            # 启动音频录制
            self.audio_recording = self.audio_var.get()
            if self.audio_recording:
                self.audio_thread = threading.Thread(target=self.record_audio)
                self.audio_thread.daemon = True
                self.audio_thread.start()
                
            # 设置摄像头录制标志
            self.camera_recording = self.camera_var.get()
                
            # 更新UI状态
            self.recording = True
            self.paused = False
            self.start_time = time.time()
            self.elapsed_time = 0
            self.frame_count = 0
            self.actual_fps = 0
            
            self.start_btn.config(state=tk.DISABLED)
            self.pause_btn.config(state=tk.NORMAL)
            self.stop_btn.config(state=tk.NORMAL)
            self.status_var.set("🔴 录制中...")
            
            # 更新按钮文本
            self.pause_btn.config(text="⏸️ 暂停")
            
            # 最小化窗口以避免被录制
            self.root.iconify()
            
            # 显示系统通知
            self.show_notification("开始录制", "屏幕录制已开始，按F10停止录制")
            
            # 开始录制线程
            self.recording_thread = threading.Thread(target=self.record_screen, 
                                                   args=(resolution, fps))
            self.recording_thread.daemon = True
            self.recording_thread.start()
            
            # 开始计时器
            self.update_timer()
            
        except Exception as e:
            messagebox.showerror("错误", f"启动录制失败: {str(e)}")
        
    def show_notification(self, title, message):
        """显示系统通知"""
        try:
            if sys.platform == "win32":
                try:
                    from win10toast import ToastNotifier
                    toaster = ToastNotifier()
                    toaster.show_toast(title, message, duration=3)
                except:
                    # 备用通知方式
                    pass
        except:
            pass
        
    def pause_recording(self):
        if self.paused:
            # 继续录制
            self.paused = False
            self.start_time = time.time()
            self.pause_btn.config(text="⏸️ 暂停")
            self.status_var.set("🔴 录制中...")
        else:
            # 暂停录制
            self.paused = True
            self.elapsed_time += time.time() - self.start_time
            self.pause_btn.config(text="▶️ 继续")
            self.status_var.set("🟡 已暂停")
            
    def stop_recording(self):
        try:
            self.recording = False
            self.audio_recording = False
            self.paused = False
            
            # 等待录制线程结束
            if hasattr(self, 'recording_thread') and self.recording_thread.is_alive():
                self.recording_thread.join(timeout=2.0)
                
            # 等待音频线程结束
            if self.audio_thread and self.audio_thread.is_alive():
                self.audio_thread.join(timeout=2.0)
                
            # 释放视频写入器
            if self.video_writer:
                self.video_writer.release()
                self.video_writer = None
                
            # 保存音频文件
            audio_file_path = None
            if self.audio_frames:
                audio_file_path = os.path.splitext(self.file_path)[0] + ".wav"
                wf = wave.open(audio_file_path, 'wb')
                wf.setnchannels(2)
                wf.setsampwidth(self.audio.get_sample_size(pyaudio.paInt16))
                wf.setframerate(44100)
                wf.writeframes(b''.join(self.audio_frames))
                wf.close()
                self.audio_frames = []
                
            # 更新UI状态
            self.start_btn.config(state=tk.NORMAL)
            self.pause_btn.config(state=tk.DISABLED, text="⏸️ 暂停")
            self.stop_btn.config(state=tk.DISABLED)
            
            # 恢复窗口
            self.root.deiconify()
            self.root.lift()
            self.root.focus_force()
            
            # 显示完成通知
            if os.path.exists(self.file_path):
                file_size = os.path.getsize(self.file_path)
                file_size_mb = file_size / (1024 * 1024)
                
                # 计算实际视频时长
                cap = cv2.VideoCapture(self.file_path)
                video_fps = cap.get(cv2.CAP_PROP_FPS)
                video_frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
                video_duration = video_frame_count / video_fps if video_fps > 0 else 0
                cap.release()
                
                status_text = f"🟢 录制完成！文件大小: {file_size_mb:.1f}MB, 帧数: {self.frame_count}, 视频时长: {video_duration:.1f}秒"
                
                if audio_file_path:
                    status_text += f", 音频已保存"
                
                self.status_var.set(status_text)
                self.show_notification("录制完成", f"视频已保存到: {os.path.basename(self.file_path)}")
            else:
                self.status_var.set("🟢 录制已停止")
            
        except Exception as e:
            messagebox.showerror("错误", f"停止录制失败: {str(e)}")
        
    def record_screen(self, resolution, fps):
        """屏幕录制线程 - 使用固定20帧率"""
        frame_interval = 1.0 / fps
        last_frame_time = time.time()
        next_frame_time = last_frame_time
        
        while self.recording:
            if not self.paused:
                try:
                    current_time = time.time()
                    
                    # 如果已经过了下一帧的时间，就捕获屏幕
                    if current_time >= next_frame_time:
                        # 捕获屏幕
                        screenshot = pyautogui.screenshot()
                        frame = np.array(screenshot)
                        frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
                        
                        # 如果启用了摄像头录制，添加摄像头画中画
                        if self.camera_recording and self.camera and self.camera.isOpened():
                            ret, cam_frame = self.camera.read()
                            if ret:
                                # 调整摄像头帧大小
                                cam_frame = cv2.resize(cam_frame, (200, 150))
                                # 将摄像头帧添加到屏幕帧的右下角
                                h, w, _ = cam_frame.shape
                                frame[10:10+h, 10:10+w] = cam_frame
                        
                        # 调整帧大小
                        if resolution != self.get_current_resolution():
                            frame = cv2.resize(frame, resolution)
                        
                        # 写入视频帧
                        if self.video_writer:
                            self.video_writer.write(frame)
                        
                        # 更新帧计数
                        self.frame_count += 1
                        
                        # 计算下一帧的时间
                        next_frame_time += frame_interval
                        
                        # 如果落后太多，重新同步
                        if next_frame_time < current_time - frame_interval * 5:
                            next_frame_time = current_time + frame_interval
                    else:
                        # 等待到下一帧的时间
                        time_to_wait = next_frame_time - current_time
                        if time_to_wait > 0:
                            time.sleep(time_to_wait)
                            
                except Exception as e:
                    print(f"录制错误: {e}")
                    time.sleep(0.1)
            else:
                time.sleep(0.1)
                
    def __del__(self):
        """清理资源"""
        if self.camera:
            self.camera.release()
        self.audio.terminate()

def main():
    root = tk.Tk()
    app = ScreenRecorder(root)
    root.mainloop()

if __name__ == "__main__":
    main()